home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Compendium Deluxe 1
/
LSD Compendium Deluxe 1.iso
/
a
/
disk
/
misc
/
string11.lha
/
strings.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-12
|
10KB
|
474 lines
/*
* FILE
* strings.c
*
* VERSION
* V1.02, Not Released
*
* DESCRIPTION
* A utility which prints out strings in binary files.
*
* This program can also be seen as a test for my "ALiLib"
* project. The program relies on 1) The clop() function for
* parsing options and
* 2) My version of malloc/free is also used. I don't know wheter
* or not it differs from the lattice version, but Lattice is
* known not to be simple......
*
* STATUS
* All rights reserved.
*
* AUTHOR
* Anders 'ALi' Lindgren
* Mälarblick 8
* S-161 51 Bromma
* Sweden
*
* CODE HISTORY
* Some years ago Idea
* 90-Dec-10 Preliminary specs written during some booring
* army radio guard night-hours.
* 90-Dec-16 Start of hacking, Program basically ready.
* Several fancy details included, like ctrl-C.
* 91-Jan-09 V1.01 Skip starting blanks
* 92-Jan-12 V1.02 View only strings terminated by NIL, CR, LF or
* TAB and long strings (which doesn't fit into
* the buffer).
* Static version string added.
*
* SEE ALSO
* ALiLib-documentation
* strings.doc
*
* TODO
* ALiLib-interfacing.
* A 0xFF (ÿ) remover? (option?)
*/
static char * version_strings = "\0$VER: strings V1.02 (" __DATE__
") by Anders Lindgren.";
#include <exec/types.h>
#include <libraries/dos.h>
#define _USEOLDEXEC_
#include <proto/exec.h>
#include <proto/dos.h>
#include <ctype.h>
#include "stdlib.h" /* It doesn't hurt if it's my own. */
#include "clop.h"
/*
* DEFINITIONS
*/
#define BUFSIZE 512 /* Remember, it's stored on the stack */
/*
* WARNING! These definitions corresponds to the clop_array below!
*/
#define OPTION_SMALL 0
#define OPTION_EXTENDED 1
#define OPTION_BYTE 2
#define OPTION_OUTPUT 3
#define OPTION_USAGE 4
#define OPTION_HELP 5
#define DOS_PRINT(x) Write(Output(),(x),sizeof(x))
#define tohex(x) ((x)>9?(x)+'A'-10:(x)+'0')
/*
* DEFINE
* isprint()
*
* DESCRIPTION
* A simple Amiga-specific isprint(). This is much shorter than
* dragging in a _ctype array.
*/
#ifdef isprint
#undef isprint
#endif
#define isprint(c) ((((c)>=32) && ((c)<=126)) || (((c)>=160) && ((c)<=255)))
/*
* FORWARD REFERENCES
*/
extern int parse_opts(char *, struct clop_array *);
extern int aloha(BPTR, BPTR, int, int, int);
extern void write_offset(BPTR, unsigned long);
/*
* GLOBAL VARIABLES
*/
struct DosLibrary * DOSBase;
/*
* FUNCTION
* not_main
*
* DESCRIPTION
*/
int __saveds __asm
not_main(register __a0 char * cline, register __d0 long len)
{
int rc;
char * args;
struct clop_list clop_list = { NULL, '\0' };
struct clop_array clop_array [ ] = {
{ 'n', CLOPT_UNUMBER, 0, 0, 6L }, /* Shortest string to print */
{ 'e', CLOPT_BOOL, 0, 0, 0L }, /* Extended character set */
{ 'b', CLOPT_BOOL, 0, 0, 0L }, /* Byte offsets */
{ 'o', CLOPT_STRING, 0, 0, NULL }, /* Output file */
{ 'u', CLOPT_BOOL, 0, 0, 0L },
{ '?', CLOPT_BOOL, 0, 0, 0L }, /* Help page */
{ '\0', CLOPT_END, 0, 0, NULL }
};
rc = RETURN_FAIL;
if (DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 0L)) {
cline[len - 1] = '\0';
if (args = clop(cline, & clop_list, clop_array)) {
if (clop_array[OPTION_HELP].value.bool ||
clop_array[OPTION_USAGE].value.bool) {
rc = RETURN_OK;
DOS_PRINT(
"Strings V1.01 Written by Anders Lindgren.\n"
"usage: strings [-nX] [-e] [-b] [-ooutfile] [infile]\n"
" -n Smallest string to print. (default 6)\n"
" -e Use extended character set.(default disabled)\n"
" -b Print out byte offset. (default disabled)\n"
" -o Print out to a file insted of standard out.\n" );
}
else {
rc = parse_opts( args, clop_array );
}
}
else {
if (clop_list.error == CLOPE_UNKNOWN_OPTION) {
DOS_PRINT("strings:Unknown switch: -");
Write(Output(), & clop_list.failing_opt, 1);
DOS_PRINT("\n");
}
else {
DOS_PRINT("strings:Incorrect usage of switch: -");
Write(Output(), & clop_list.failing_opt, 1);
DOS_PRINT("\n");
}
}
/*
* Free everything allocated.
*/
freeclop(clop_array);
CloseLibrary((struct Library *)DOSBase);
}
return (rc);
}
/*
* FUNCTION
* parse_opts
*
* DESCRIPTION
* Open all files, and establish all flags etc.
*
* Rename function? Guess so....
*/
int
parse_opts( char * filename, struct clop_array * clop_array)
{
BPTR input;
BPTR output;
/* Flags, using opened input/output FH, instead of std* */
int closein;
int closeout;
unsigned int smallest;
char * ofn; /* Output file name */
int rc; /* Returncode */
rc = RETURN_FAIL;
smallest = clop_array[OPTION_SMALL].value.unumber;
if ((smallest < BUFSIZE) && (smallest > 0) ) {
/*
* Establish an input stream.
*/
if (* filename) {
if (input = Open(filename, MODE_OLDFILE)) {
closein = TRUE;
}
else {
DOS_PRINT("strings:Didn't find input file.\n");
return (RETURN_FAIL);
}
}
else {
input = Input();
closein = FALSE;
}
/*
* Establish output stream.
*/
if (ofn = clop_array[OPTION_OUTPUT].value.string) {
if (* ofn) {
closeout = TRUE;
if ( (output = Open(ofn, MODE_NEWFILE)) == NULL) {
if (closein) {
Close(input);
}
DOS_PRINT("strings:Error opening output file.\n");
return(RETURN_FAIL);
}
}
else {
if (closein) {
Close(input);
}
DOS_PRINT("strings:Missing output filename.\n");
return(RETURN_FAIL);
}
}
else {
output = Output();
closeout = FALSE;
}
/*
* Call the actual heart of the program, and serv it all
* it want to know on a silver plate.
*/
rc = aloha(input, output, smallest,
clop_array[OPTION_EXTENDED].value.bool,
clop_array[OPTION_BYTE].value.bool);
/*
* Clean up files
*/
if (closein) {
Close(input);
}
if (closeout) {
Close(output);
}
}
else {
DOS_PRINT("strings:Illegal -n number.\n");
}
return(rc);
}
/*
* FUNCTION
* aloha
*
* DESCRIPTION
* The actual main loop.
*
* The name? Naw, I really can't think of any good, since
* it's only a main, level 3.
*
* SYNOPSIS
* aloha(input, output, smallest, extended, byteflg)
* input, output - AmigaDOS filehandlers.
* smallest - Shortest length to bother to print
* extended - (flag) Consider the extended characters.
* byteflg - (flag) Print out the byteoffset.
*/
int
aloha(BPTR input, BPTR output, int smallest, int extended, int byteflg)
{
unsigned char inbuf [BUFSIZE];
unsigned char outbuf[BUFSIZE];
int soffset;
int doffset = 0;
long counter = 0;
long byteoffset = 0;
unsigned char ch;
int al; /* Actual length read */
/* A _very_ long output line, longer than one buffer. */
int longflg = FALSE;
int ctrlc = FALSE;
do { /* Until eof, or ctrl-C pressed */
al = Read(input, inbuf, BUFSIZE);
/* Check each character in the input buffer */
for (soffset = 0; ( (soffset < al) && ! ctrlc ); soffset++) {
ch = inbuf[soffset];
/*
* Check if the character is printable.
*/
if ( isprint(ch) && (extended || isascii(ch)) ) {
/*
* Don't register spaces if they start a string.
*/
if (ch != ' ' || doffset != 0 || longflg) {
/*
* Save the position for this string
*/
if ((doffset == 0) && (! longflg)) {
byteoffset = counter;
}
outbuf[doffset++] = ch;
/*
* Is the output buffer full?
* Let's empty it and flag.
*/
if (doffset == BUFSIZE) {
if ( (! longflg) && (byteflg) ) {
write_offset(output, byteoffset);
}
Write(output, outbuf, BUFSIZE);
longflg = TRUE;
doffset = 0;
}
}
}
else {
/*
* A nonprintable character found, let's see
* if the characters found before if it's long
* enough to print, or if the characters in
* the buffer is part of a earlier, very long,
* string.
*
* 1992-01-12: Just strings which are terminated
* by NIL, CR, LF or TAB are considered
* strings, if the string aren't so
* big so it doesn't fit the buffer,
* in which case we will se it anyway.
*/
if ( ( ((ch == '\0') ||
(ch == 10) ||
(ch == 13) ||
(ch == 9)) && (doffset >= smallest) ) ||
longflg ) {
if ( (! longflg) && (byteflg) ) {
write_offset(output, byteoffset);
}
Write(output, outbuf, doffset);
Write(output, "\n", 1);
}
doffset = 0;
longflg = FALSE;
}
counter++; /* Byte counter */
if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C) {
ctrlc = TRUE;
}
}
} while((al > 0) && (!ctrlc));
/*
* If the file ended, and we have a correct strings in our
* buffer, print it out.
*/
if (ctrlc) {
DOS_PRINT("*** Break!\n");
}
else if ((doffset >= smallest) || longflg) {
if ( (! longflg) && (byteflg) ) {
write_offset(output, byteoffset);
}
Write(output, outbuf, doffset);
Write(output, "\n", 1);
}
return(al >= 0 ? RETURN_OK : RETURN_ERROR);
}
/*
* FUNCTION
* write_offset
*
* DESCRIPTION
* This function writes out the offset in the form:
* "X:" where X are at four or eigth hexadecimal
* digits.
*/
void
write_offset(BPTR output, unsigned long offset)
{
char outbuf[9];
int i;
int firstn0;
outbuf[8] = ':';
/*
* Decide if we shall print out four hexadecial digits, or
* if we need all eight.
*/
firstn0 = offset & 0xFFFF0000 ? 0 : 4;
for (i=7; i>=0; i--) {
outbuf[i] = tohex(offset & 0x0F);
offset >>= 4;
}
Write(output, & outbuf[firstn0], 9-firstn0);
return;
}